<?php
/**
 * Created by PhpStorm.
 * User: whwyy
 * Date: 2018/11/8 0008
 * Time: 18:06
 */

namespace BeReborn\Service\Common;

use Exception;
use Swoole\Server;
use BeReborn\Error\Logger;
use BeReborn\Task\InterfaceTask;
use Swoole\Timer;
use Swoole\Coroutine;
use BeReborn\Service\Base\ServerBase;

/**
 * Class ServerTask
 * @package BeReborn\Server
 */
class ServerTask extends ServerBase
{

	const AFTER_TASK = 'AFTER_TASK';

	/**
	 * @param Server $server
	 * @param int $task_id
	 * @param int $from_id
	 * @param string $data
	 *
	 * @return mixed|void
	 * @throws Exception
	 * 异步任务
	 */
	public function onTask(Server $server, $task_id, $from_id, $data)
	{
		$time = microtime(TRUE);
		if (empty($data)) {
			return $server->finish('null data');
		}
		$finish = $this->runTaskHandler($data);
		if (!$finish) {
			$finish = [];
		}
		$finish['runTime'] = [
			'startTime' => $time,
			'runTime'   => microtime(TRUE) - $time,
			'endTime'   => microtime(TRUE),
		];
		$server->finish(json_encode($finish));
	}

	/**
	 * @param Server $server
	 * @param Server\Task $task
	 * @return mixed|void
	 * @throws Exception
	 * 异步任务
	 */
	public function onContinueTask(Server $server, $task)
	{
		$time = microtime(TRUE);
		if (empty($task->data)) {
			return $task->finish('null data');
		}
		$finish = $this->runTaskHandler($task->data);
		if (!$finish) {
			$finish = [];
		}
		$finish['runTime'] = [
			'startTime' => $time,
			'runTime'   => microtime(TRUE) - $time,
			'endTime'   => microtime(TRUE),
		];
        $task->finish(json_encode($finish));
	}

	/**
	 * @param $data
	 * @return array|null
	 * @throws Exception
	 */
	private function runTaskHandler($data)
	{
		$serialize = unserialize($data);
		if (empty($serialize) || !($serialize instanceof InterfaceTask)) {
			return null;
		}
		try {
			$params = $serialize->getParams();
			if (is_object($params)) {
				$params = get_object_vars($params);
			}
			$finish = [
				'class'  => get_class($serialize),
				'params' => $params
			];

			$finish['status'] = 'success';
			$finish['info'] = $serialize->handler();
		} catch (\Throwable $exception) {
			Logger::error($exception, 'Task');
			$message = $exception->getMessage() . " on line " . $exception->getLine() . " at file " . $exception->getFile();

			$finish['status'] = 'error';
			$finish['info'] = $message;
		} finally {
			fire(static::AFTER_TASK);
			Timer::clearAll();
			Logger::insert();
		}
		return $finish;
	}

	/**
	 * @param Server $server
	 * @param $task_id
	 * @param $data
	 * @throws Exception
	 */
	public function onFinish(Server $server, $task_id, $data)
	{
	}
}
